using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using QQ.Framework.Utils;

namespace QQ.Framework.Packets.Send.Message
{
    /// <summary>
    ///     发送消息
    /// </summary>
    public class Send_0X0002 : SendPacket
    {
        public long _group { get; set; }

        private readonly byte _packetCount = 1;
        private byte _packetIndex;

        public List<Send_0X0002> Following;
        private readonly byte[] _data;

        public Send_0X0002(QQUser user, Richtext message, long group)
            : base(user)
        {
            Sequence = GetNextSeq();
            SecretKey = user.TXProtocol.SessionKey;
            Command = QQCommand.Message0X0002;
            Message = message;
            _group = group;
            Following = new List<Send_0X0002>();
            var data = Util.WriteRichtext(message);
            var count = data.Count;
            var index = 1;
            _data = data[0];
            data.RemoveAt(0);
            foreach (var part in data)
            {
                Following.Add(new Send_0X0002(user, part, group, index++, count));
            }
        }

        private Send_0X0002(QQUser user, byte[] data, long group, int index, int count) : base(user)
        {
            Sequence = GetNextSeq();
            SecretKey = user.TXProtocol.SessionKey;
            Command = QQCommand.Message0X0002;
            _data = data;
            _group = group;
            _packetIndex = (byte)index;
            _packetCount = (byte)count;
        }

        /// <summary>
        ///     消息类型
        /// </summary>
        public MessageType MessageType { get; set; }

        public Richtext Message { get; }
        /// <summary>
        ///     消息 id
        /// </summary>
        public byte[] MessageId { get; set; }
        /// <summary>
        /// 消息索引
        /// </summary>
        public byte[] MessageIndex { get; set; }

        protected override void PutHeader()
        {
            base.PutHeader();
            SendPACKET_FIX();
        }

        /// <summary>
        ///     初始化包体
        /// </summary>
        protected override void PutBody()
        {
            var dateTime = Util.GetTimeSeconds(DateTime.Now);
            var group = ConvertQQGroupId(_group);
            switch (Message.Snippets[0].Type)
            {
                case MessageType.At:
                case MessageType.Normal:
                case MessageType.Emoji:
                    {
                        BodyWriter.Write((byte)0x2A);
                        BodyWriter.BeWrite(group);
                        BodyWriter.BeWrite((ushort)(_data.Length + 50)); // 字符串长度 + 56，但是_data里面包含了和长度有关的额外六个byte
                        BodyWriter.Write(new byte[]
                        {
                        0x00, 0x01, _packetCount, _packetIndex, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x53,
                        0x47, 0x00,
                        0x00, 0x00, 0x00, 0x00
                        });
                        BodyWriter.BeWrite(dateTime);
                        BodyWriter.Write(Util.RandomKey(4));
                        BodyWriter.Write(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x86, 0x00 });
                        BodyWriter.Write(new byte[] { 0x00, 0x0C });
                        BodyWriter.Write(new byte[]
                            {0xE5, 0xBE, 0xAE, 0xE8, 0xBD, 0xAF, 0xE9, 0x9B, 0x85, 0xE9, 0xBB, 0x91});
                        BodyWriter.Write(new byte[] { 0x00, 0x00 });
                        BodyWriter.Write(_data);
                        break;
                    }
                case MessageType.Xml:
                    {
                        BodyWriter.Write((byte)0x2A);
                        BodyWriter.BeWrite(group);
                        var compressMsg = GZipByteArray.CompressBytes(Message.Snippets[0].Content);
                        BodyWriter.BeWrite((ushort)(compressMsg.Length + 64));
                        BodyWriter.Write(new byte[]
                        {
                        0x00, 0x01, _packetCount, _packetIndex, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x53,
                        0x47, 0x00,
                        0x00, 0x00, 0x00, 0x00
                        });
                        BodyWriter.BeWrite(dateTime);
                        BodyWriter.Write(SendXml(compressMsg));
                        break;
                    }
                case MessageType.Picture:
                    {
                        var _Snippets = Message.Snippets[0];
                        BodyWriter.Write((byte)0x2A);
                        BodyWriter.BeWrite(group);
                        var guid = Encoding.UTF8.GetBytes(Util.GetMD5ToGuidHashFromFile(Message.Snippets[0].Content) + Path.GetExtension(_Snippets.Content));
                        BodyWriter.Write(new byte[] { 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x53, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00 });
                        BodyWriter.BeWrite(dateTime);
                        BodyWriter.Write(Util.RandomKey(4));
                        BodyWriter.Write(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x86, 0x22 });
                        BodyWriter.WriteKey(new byte[] { 0xE5, 0xBE, 0xAE, 0xE8, 0xBD, 0xAF, 0xE9, 0x9B, 0x85, 0xE9, 0xBB, 0x91 });
                        BodyWriter.Write(new byte[] { 0x00, 0x00, 0x03, 0x00, 0xCB, 0x02 });
                        BodyWriter.WriteKey(guid);
                        BodyWriter.Write((byte)0x04);
                        BodyWriter.WriteKey(Util.HexStringToByteArray(_Snippets["30Key"].ToString()));
                        BodyWriter.Write((byte)0x05);
                        BodyWriter.WriteKey(Util.HexStringToByteArray(_Snippets["48Key"].ToString()));
                        BodyWriter.Write(new byte[]
                        {
                            0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x50, 0x07, 0x00, 0x01, 0x43,
                            0x08, 0x00, 0x00, 0x09, 0x00, 0x01, 0x01, 0x0b, 0x00, 0x00, 0x14,
                            0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x00,
                            0x05, 0xa0, 0x16, 0x00, 0x04, 0x00, 0x00, 0x04, 0x38, 0x18, 0x00,
                            0x04, 0x00, 0x01, 0xf5, 0x62, 0xff
                        });

                        var data = new BinaryWriter(new MemoryStream());
                        data.Write(new byte[] { 0x15, 0x36, 0x20 });
                        data.Write(new byte[]
                        {
                            0x39, 0x32, 0x6b, 0x41, 0x31, 0x43, 0x61, 0x37, 0x64, 0x63, 0x66,
                            0x34, 0x38, 0x37, 0x34, 0x39, 0x38, 0x64, 0x33, 0x33, 0x37, 0x39
                        });
                        data.Write(new byte[]
                        {
                            0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x35, 0x30, 0x20, 0x20, 0x20,
                            0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                            0x20, 0x20
                        });
                        data.Write(guid);
                        data.Write((byte)0x41);
                        BodyWriter.WriteKey(data.BaseStream.ToBytesArray());
                        break;
                    }
                case MessageType.AddGroup:
                    {
                        BodyWriter.Write(new byte[] { 0x08 });
                        BodyWriter.BeWrite(group);
                        BodyWriter.Write(new byte[] { 0x01 });
                        BodyWriter.BeWrite((ushort)User.AddFriend0020Value.Length);
                        BodyWriter.Write(User.AddFriend0020Value);
                        BodyWriter.Write(new byte[] { 0x00, 0x00, 0x00 });
                        //备注信息
                        var messageData = Encoding.UTF8.GetBytes(Message.Snippets[0].Content);
                        Writer.BeWrite((ushort)messageData.Length);
                        Writer.Write(messageData);
                        BodyWriter.Write(new byte[] { 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x09 });
                        break;
                    }
                case MessageType.GetGroupImformation:
                    {
                        BodyWriter.Write(new byte[] { 0x72 });
                        BodyWriter.BeWrite(group);
                        BodyWriter.BeWrite(0x00);
                        break;
                    }
                case MessageType.ExitGroup:
                    {
                        BodyWriter.Write(new byte[] { 0x09 });
                        BodyWriter.BeWrite(group);
                        break;
                    }
                default:
                    {
                        throw new NotImplementedException();
                    }
            }
        }


        public long ConvertQQGroupId(long code)
        {
            var group = code.ToString();
            var left = Convert.ToInt64(group.Substring(0, group.Length - 6));
            string right = "", gid = "";
            if (left >= 1 && left <= 10)
            {
                right = group.Substring(group.Length - 6, 6);
                gid = (left + 202).ToString() + right;
            }
            else if (left >= 11 && left <= 19)
            {
                right = group.Substring(group.Length - 6, 6);
                gid = (left + 469).ToString() + right;
            }
            else if (left >= 20 && left <= 66)
            {
                left = Convert.ToInt64(left.ToString().Substring(0, 1));
                right = group.Substring(group.Length - 7, 7);
                gid = (left + 208).ToString() + right;
            }
            else if (left >= 67 && left <= 156)
            {
                right = group.Substring(group.Length - 6, 6);
                gid = (left + 1943).ToString() + right;
            }
            else if (left >= 157 && left <= 209)
            {
                left = Convert.ToInt64(left.ToString().Substring(0, 2));
                right = group.Substring(group.Length - 7, 7);
                gid = (left + 199).ToString() + right;
            }
            else if (left >= 210 && left <= 309)
            {
                left = Convert.ToInt64(left.ToString().Substring(0, 2));
                right = group.Substring(group.Length - 7, 7);
                gid = (left + 389).ToString() + right;
            }
            else if (left >= 310 && left <= 499)
            {
                left = Convert.ToInt64(left.ToString().Substring(0, 2));
                right = group.Substring(group.Length - 7, 7);
                gid = (left + 349).ToString() + right;
            }
            else
            {
                return code;
            }

            return Convert.ToInt64(gid);
        }
    }
}